import axios, { AxiosRequestConfig, Method } from 'axios'
import { ElLoading, ElMessage } from 'element-plus'
import Qs from 'qs'
import jsCookie from 'js-cookie'
import router from '../router/index'

// 初始化loading
let loading: any

// 开始加载动画
function startLoading() {
    loading = ElLoading.service({
        lock: true,
        text: '加载中...'
    })
}
// 结束加载动画
function endLoading() {
    loading.close()
}

axios.defaults.baseURL = ''
// 设置默认的请求超时时间
axios.defaults.timeout = 20000
// post请求头的设置
// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
// 默认使用application/json的提交方式
axios.defaults.headers.post['Content-Type'] = 'application/json'

// 拦截器 在请求或响应被 then 或 catch 处理前拦截它们
// 请求拦截器
axios.interceptors.request.use(
    config => {
        // 在发送请求之前做些什么
        // 每次发送请求之前判断是否存在token，如果存在，则统一在http请求的header都加上token，不用每次请求都手动添加了
        // 即使本地存在token，也有可能token是过期的，所以在响应拦截器中要对返回状态进行判断
        const token = jsCookie.get('token')
        config.headers.token = token
        startLoading()
        return config
    },
    // 对请求错误做些什么
    error => {
        setTimeout(() => {
            endLoading()
            // message.error('请求超时了，请刷新重试！！！')
        }, 20000)
        return Promise.reject(error)
    }
)

// 响应拦截器
axios.interceptors.response.use(
    // 对响应数据做点什么
    response => {
        if (response.data.statusCode === 200) {
            endLoading()
            return Promise.resolve(response)
        } else {
            endLoading()
            return Promise.reject(response)
        }
    },
    // 对响应错误做点什么
    error => {
        endLoading()
        return Promise.reject(error)
    }
)

export function HAjax(url: string = '', params: any = {}, method: any = 'GET', type: string = '') {
    url = axios.defaults.baseURL + url

    // get/delete请求
    if (method.toLowerCase() === 'get' || method.toLowerCase() === 'delete') {
        let query: any = []
        for (const key in params) {
            const value = params[key] !== undefined ? params[key] : ''
            query.push(key + '=' + value)
        }
        query = query.join('&')
        url += (url.indexOf('?') < 0 ? '?' : '&') + query
    }
    // post/put/patch请求
    if (method.toLowerCase() === 'post' || method.toLowerCase() === 'put' || method.toLowerCase() === 'patch') {
        // formData的提交方式Qs.stringify(params)
        // params = Qs.stringify(params)
        // application/json的post提交方式使用JSON.stringify(params)
        // params = JSON.stringify(params)
        if (type === 'formData') {
            axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'
            params = Qs.stringify(params)
            console.log(params) // key=value&key=value
        } else if (type === 'file') {
            let formData = new FormData()
            formData.append('file', params.file)
            params = formData
        } else {
            axios.defaults.headers.post['Content-Type'] = 'application/json'
            params = JSON.stringify(params)
            console.log(params) //{"key":value}
        }
    }
    const config: AxiosRequestConfig = {
        method: method,
        url: url,
        data: params
    }
    return new Promise<any>((resolve, reject) => {
        axios(config)
            .then(response => {
                if (response.data.statusCode === 200) {
                    resolve(response.data)
                } else {
                    ElMessage.error(response.data.data.message)
                }
            })
            .catch(error => {
                if (error.data.statusCode === 401) {
                    jsCookie.remove('token')
                    ElMessage({
                        message: 'token 失效，请重新登录',
                        type: 'error',
                        onClose: () => {
                            router.push({
                                path: '/login'
                            })
                        }
                    })
                } else {
                    ElMessage.error(error.data.data.message)
                }
                reject(error)
            })
    })
}
